﻿namespace LaoLuo
{
    using System.Collections.Generic;
    using System.Linq;
    using System;

    /// <summary>
    /// 将数据分批装入一定容量的箱子的容器
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    public class BoxedContainer<T> : IEnumerable<IEnumerable<T>>
    {
        /// <summary>
        /// 容器中所有的数据
        /// </summary>
        private readonly List<T> _values;

        /// <summary>
        /// 每个箱子的容量
        /// </summary>
        private readonly int _capacity;

        /// <summary>
        /// 初始化一个容器
        /// </summary>
        /// <param name="capacity">箱子的容量</param>
        /// <param name="values">初始数据</param>
        public BoxedContainer(int capacity, IEnumerable<T> values = null)
        {
            this._capacity = capacity;

            this._values = (values ?? Enumerable.Empty<T>()).ToList();
        }

        /// <summary>
        /// 箱子的个数
        /// </summary>
        public int BoxCount
        {
            get
            {
                return MathHelper.QuotientCeiling(this._values.Count, this._capacity);
            }
        }

        public IEnumerable<T> Values
        {
            get
            {
                foreach (var box in this)
                {
                    foreach (var value in box)
                    {
                        yield return value;
                    }
                }
            }
        }

        /// <summary>
        /// 容器中所有的数据的数量
        /// </summary>
        public int Count
        {
            get
            {
                return this._values.Count;
            }
        }

        /// <summary>
        /// 获取指定箱子的数据
        /// </summary>
        /// <param name="index">箱子的index</param>
        /// <returns>箱子中的数据</returns>
        public IEnumerable<T> this[int index]
        {
            get
            {
                return this.GetBox(index);
            }
        }

        /// <summary>
        /// 添加一条数据
        /// </summary>
        /// <param name="value">数据</param>
        public void Add(T value)
        {
            this._values.Add(value);
        }

        /// <summary>
        /// 返回箱子的枚举器
        /// </summary>
        /// <returns>枚举器</returns>
        public IEnumerator<IEnumerable<T>> GetEnumerator()
        {
            for (var i = 0; i < this.BoxCount; i++)
            {
                yield return this[i];
            }
        }

        /// <summary>
        /// 返回箱子的枚举器
        /// </summary>
        /// <returns>枚举器</returns>
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        /// <summary>
        /// 获取指定箱子的数据
        /// </summary>
        /// <param name="index">箱子的index</param>
        /// <returns>箱子中的数据</returns>
        protected IEnumerable<T> GetBox(int index)
        {
            return this._values.Skip(index * this._capacity).Take(this._capacity);
        }
    }
}
